﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Syngine.Components.Shapes
{
	/// <summary>
	/// 
	/// </summary>
	public struct Line : IDraw
	{
		private static Texture2D _texture;

		private readonly Color _color;
		private Vector2 _start;
		private Vector2 _end;
		private bool _visible;
		private int _drawOrder;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="color"></param>
		public Line(Color color) : this()
		{
			_color = color;
			_visible = false;
			_drawOrder = 0;
			DrawOrderChanged = null;
			VisibleChanged = null;
			Distance = 0;
			Direction = 0;
			IsInitialized = false;
		}

		/// <summary>
		/// 
		/// </summary>
		public event EventHandler<EventArgs> DrawOrderChanged;

		/// <summary>
		/// 
		/// </summary>
		public event EventHandler<EventArgs> VisibleChanged;

		/// <summary>
		/// 
		/// </summary>
		public int DrawOrder
		{
			get
			{
				return _drawOrder;
			}
			set
			{
				if (_drawOrder != value)
				{
					_drawOrder = value;
					OnDrawOrderChanged();
				}
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public bool Visible
		{
			get
			{
				return _visible;
			}
			set
			{
				if (_visible != value)
				{
					_visible = value;
					OnVisibleChanged();
				}
				_visible = value;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public Vector2 EndPosition
		{
			get
			{
				return _end;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public Vector2 StartPosition
		{
			get
			{
				return _start;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public float Distance { get; set; }

		/// <summary>
		/// 
		/// </summary>
		public float Direction { get; set; }

		/// <summary>
		/// 
		/// </summary>
		public bool IsInitialized { get; private set; }

		/// <summary>
		/// 
		/// </summary>
		public void Initialize()
		{
			IsInitialized = true;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="start"></param>
		/// <param name="end"></param>
		public void UpdateDirection(Vector2 start, Vector2 end)
		{
			_start = start;
			_end = end;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		public void Update(UpdateContext context)
		{
			Direction = (float)Math.Atan2(StartPosition.Y - EndPosition.Y, StartPosition.X - EndPosition.X);
			Distance = Vector2.Distance(StartPosition, EndPosition);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		public void LoadContent(LoadContext context)
		{
			if (_texture == null)
			{
				_texture = new Texture2D(GameContext.Game.GraphicsDevice, 1, 1, false, SurfaceFormat.Color);
				_texture.SetData(new[] { Color.White }, 0, _texture.Width * _texture.Height);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public void UnloadContent()
		{
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		public void Draw(DrawContext context)
		{
			if (Visible)
			{
				var rectangle = new Rectangle((int)StartPosition.X, (int)StartPosition.Y, (int)Distance, 1);
				context.SpriteBatch.Draw(_texture, rectangle, null, _color, Direction, Vector2.Zero, SpriteEffects.None, 0f);
			}
		}

		private void OnVisibleChanged()
		{
			var handler = VisibleChanged;

			if (handler != null)
			{
				handler(this, EventArgs.Empty);
			}
		}

		private void OnDrawOrderChanged()
		{
			var handler = DrawOrderChanged;

			if (handler != null)
			{
				handler(this, EventArgs.Empty);
			}
		}
	}
}